package ctest

import chisel3._
import chisel3.util._
import common.Consts._
//import chisel3.util.experimental.loadMemoryFromFile
import scala.io.Source

class ImemPortIo extends Bundle {
  val addr = Input(UInt(WORD_LEN.W))
  val inst = Output(UInt(WORD_LEN.W))
}

class DmemPortIo extends Bundle {
  val addr  = Input(UInt(WORD_LEN.W))
  val rdata = Output(UInt(WORD_LEN.W))
  val wen   = Input(Bool())
  val wdata = Input(UInt(WORD_LEN.W))
}

class Memory extends Module {
  val io = IO(new Bundle {
    val imem = new ImemPortIo()
    val dmem = new DmemPortIo()
  })

  val mem = Mem(16384, UInt(8.W))
  //loadMemoryFromFile(mem, "src/hex/ctest.hex")
  var fileLines = Source.fromFile("src/hex/ctest.hex").getLines().toList
  for((line, index) <- fileLines.zipWithIndex) {
    val num: Int = Integer.parseInt(line, 16)
    val idxBits: UInt = index.asUInt
    val lineBits: UInt = num.asUInt
    mem(index) := lineBits
    //chisel3.printf(p"fromFile: Index: ${idxBits}, Content: ${lineBits}, mem: ${mem(index)}\n")
  }

  io.imem.inst := Cat(
    mem(io.imem.addr + 3.U(WORD_LEN.W)), 
    mem(io.imem.addr + 2.U(WORD_LEN.W)),
    mem(io.imem.addr + 1.U(WORD_LEN.W)),
    mem(io.imem.addr)
  )
  chisel3.printf("io.imem.addr = 0x%x,    io.imem.inst = 0x%x\n",io.imem.addr,  io.imem.inst)

  io.dmem.rdata := Cat(
    mem(io.dmem.addr + 3.U(WORD_LEN.W)),
    mem(io.dmem.addr + 2.U(WORD_LEN.W)), 
    mem(io.dmem.addr + 1.U(WORD_LEN.W)),
    mem(io.dmem.addr)
  )
  chisel3.printf("io.dmem.addr = 0x%x,    io.dmem.rdata = 0x%x\n",io.imem.addr,  io.dmem.rdata)

  when(io.dmem.wen){
    mem(io.dmem.addr)                   := io.dmem.wdata( 7,  0)
    mem(io.dmem.addr + 1.U(WORD_LEN.W)) := io.dmem.wdata(15,  8)
    mem(io.dmem.addr + 2.U(WORD_LEN.W)) := io.dmem.wdata(23, 16)
    mem(io.dmem.addr + 3.U(WORD_LEN.W)) := io.dmem.wdata(31, 24)
    chisel3.printf("io.dmem.addr = 0x%x,    io.dmem.wdata = 0x%x\n",io.dmem.addr,  io.dmem.wdata)
  }
}
